package beans;


import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;


/**
 * This class contains all the information necessary to manage a Move
 * @author Josep M Sobrepere
 *
 */
public class Move implements Serializable{
	

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Position from;
	private Position to;
	private Piece piece;
	private Piece capturedPiece;
	private ChessPiece piecePromotion;
	private String shortAlgebraicNotation;
	private boolean check;
	private boolean mate;
	private boolean takeEnPassant;
	private boolean pawnEnPassant;
	private Move nextMove=null;
	private Move previousMove=null;
	private AnalysisInformation analysis;
	private int number;	
		
	
	/**
	 * @return returns the analysis information linked to this move
	 */
	public AnalysisInformation getAnalysis() {
		return analysis;
	}


	/**
	 * @param sets the analysis information linked to this move
	 */
	public void setAnalysis(AnalysisInformation analysis) {
		this.analysis = analysis;
	}


	/**
	 * @return returns the next move
	 */
	public Move getNextMove() {
		return nextMove;
	}


	/**
	 * @param nextMove sets the next move
	 */
	public void setNextMove(Move nextMove) {
		this.nextMove = nextMove;
	}


	/**
	 * @return returns the previous move
	 */
	public Move getPreviousMove() {
		return previousMove;
	}


	/**
	 * @param previousMove sets the previous move
	 */
	public void setPreviousMove(Move previousMove) {
		this.previousMove = previousMove;
	}
	
	/**
	 * Constructor
	 * 
	 * @param from Position from where the piece has been moved 
	 * @param to Position to where the piece has been moved
	 * @param piece Piece that has been moved
	 * @param capturedPiece piece that has been captures (can be null)
	 * @param piecePromotion piece that has been promoted (can be null)
	 * @param shortAlgebraicNotation the short algebraic notatation that represents this move
	 * @param check indicates if this moves has generated a check
	 * @param mate indicates if this move is checkmate
	 * @param pawnEnPassant indicates if there is a pawn en passant
	 * @param takeEnPassant indicates if a pawn en passant has been taken
	 * @param number number of move 
	 */
	public Move(Position from, Position to, Piece piece,
			Piece capturedPiece, ChessPiece piecePromotion,
			String shortAlgebraicNotation, boolean check, boolean mate, boolean pawnEnPassant, boolean takeEnPassant, int number) {
		super();
		this.from = from;
		this.to = to;
		this.piece = piece;
		this.capturedPiece = capturedPiece;
		this.piecePromotion = piecePromotion;
		this.shortAlgebraicNotation = shortAlgebraicNotation;
		this.check = check;
		this.mate = mate;
		this.takeEnPassant=takeEnPassant;
		this.pawnEnPassant=pawnEnPassant;
		this.number=number;
	}
	
	
	/**
	 * @return the move number
	 */
	public int getNumber() {
		return number;
	}
	/**
	 * @param number sets the move number
	 */
	public void setNumber(int number) {
		this.number = number;
	}

	/**
	 * @return the captured piece
	 */
	public Piece getCapturedPiece() {
		return capturedPiece;
	}

	/**
	 * @return if the piece has been take en passant
	 */
	public boolean isTakeEnPassant() {
		return takeEnPassant;
	}


	/**
	 * @param takeEnPassant sets if the piece has been take en passant
	 */
	public void setTakeEnPassant(boolean takeEnPassant) {
		this.takeEnPassant = takeEnPassant;
	}


	public boolean isPawnEnPassant() {
		return pawnEnPassant;
	}


	public void setPawnEnPassant(boolean pawnEnPassant) {
		this.pawnEnPassant = pawnEnPassant;
	}


	public void setCapturedPiece(Piece capturedPiece) {
		this.capturedPiece = capturedPiece;
	}


	public String getShortAlgebraicNotation() {
		return shortAlgebraicNotation;
	}


	public void setShortAlgebraicNotation(String shortAlgebraicNotation) {
		this.shortAlgebraicNotation = shortAlgebraicNotation;
	}


	public boolean isCheck() {
		return check;
	}


	public void setCheck(boolean check) {
		this.check = check;
	}


	public boolean isMate() {
		return mate;
	}


	public void setMate(boolean mate) {
		this.mate = mate;
	}

	public ChessPiece getPiecePromotion() {
		return piecePromotion;
	}
	public void setPiecePromotion(ChessPiece piecePromotion) {
		this.piecePromotion = piecePromotion;
	}
	public Position getFrom() {
		return from;
	}
	public void setFrom(Position from) {
		this.from = from;
	}
	public Position getTo() {
		return to;
	}
	public void setTo(Position to) {
		this.to = to;
	}
	
	public Piece getPiece() {
		return piece;
	}
	public void setPiece(Piece piece) {
		this.piece = piece;
	}
	@Override
	public String toString() {		
		return this.getShortAlgebraicNotation();
	}
	
	public String toLongAlgebraicFormat(){
		String res= getStrFromPosition(this.from) + getStrFromPosition(this.to);
		if(piecePromotion!=null){
			switch (piecePromotion){
			case ROOK : 
				res=res+"r";
				break;
			case KNIGHT :				
				res=res+"n";
				break;			
			case BISHOP :
				res=res+"b";
				break;			
			case QUEEN :
				res=res+"q";
				break;
			}
		}
		return res;
	}
	
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((from == null) ? 0 : from.hashCode());
		result = prime * result + ((to == null) ? 0 : to.hashCode());
		return result;
	}


	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Move other = (Move) obj;
		if (from == null) {
			if (other.from != null)
				return false;
		} else if (!from.equals(other.from))
			return false;
		if (to == null) {
			if (other.to != null)
				return false;
		} else if (!to.equals(other.to))
			return false;
		return true;
	}


	private String getStrFromPosition(Position pos){
		char x = (char) (pos.getX()+97);
		StringBuilder sb = new StringBuilder();
		sb.append(x).append((pos.getY()+1));
		return sb.toString();
	}
}
